#include "include/version.hpp"
#include "include/flag.hpp"
#include "core/core.hpp"
#include "device/device.hpp"

#include <ctime>
#include <cstdio>

#include <string>
#include <sstream>
#include <fstream>
#include <iostream>

static canyon::device::Console console;

static canyon::VM start_vm(char * rom_filename){
    std::ifstream file(rom_filename, std::ios::in|std::ios::binary);
    canyon::VM vm;
    file.read(
        (char *)vm.memory.unsafe_get_adr(),
        canyon::MEMORY_SIZE
    );
    return vm;
}

static void init_devices(canyon::Bus & bus){
    bus.add_device(&console);
}

#ifdef __CANYON_FLAG_enableLogging

static void init_logging(){
    time_t curtime;
    time(&curtime);

    tm * timer = localtime(&curtime);
    std::stringstream res;
    res << timer->tm_year + 1900
        << "-" << timer->tm_mon + 1
        << "-" << timer->tm_mday
        << " " << timer->tm_hour
        << ":" << timer->tm_min
        << ":" << timer->tm_sec;

    freopen((res.str() + ".canyon.log").c_str(), "w", stderr);
}

static void fin_logging(){
    fclose(stderr);
}

#endif

int main(int argc, char * argv[]){
#ifdef __CANYON_FLAG_enableLogging
    init_logging();
#endif

    if(argc != 2)return 1;
    canyon::VM vm = start_vm(argv[1]);
    init_devices(vm.bus);
    vm.run();

#ifdef __CANYON_FLAG_enableLogging
    fin_logging();
#endif
    return 0;
}
